package blaha.genalg.output;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;

import org.apache.log4j.Logger;

import blaha.genalg.beans.Board;
import blaha.genalg.methods.ReadAllProperties;

import blaha.logging.Log;

public class GraphML2XML {
	
	private static final Logger log  = Log.getLoggerMoje();
	
	public static String Create(Board board,ReadAllProperties settings) {

		StringBuffer sb = new StringBuffer();
		sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
		// beggining of xml document
		sb.append("<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\""); 
		sb.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""); 
		sb.append(" xmlns:y=\"http://www.yworks.com/xml/graphml\""); 
		sb.append(" xmlns:yed=\"http://www.yworks.com/xml/yed/3\""); 
		sb.append(" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd\">\n");

		// ###Node###
		//color		
		sb.append("<key for=\"graphml\" id=\"d0\" yfiles.type=\"resources\"/>\n");
		
		sb.append("<key attr.name=\"color\" attr.type=\"string\" for=\"node\" id=\"d1\">\n");
		sb.append("<default><![CDATA[yellow]]></default>\n");
		sb.append("</key>\n");
		
		sb.append("<key attr.name=\"url\" attr.type=\"string\" for=\"node\" id=\"d2\"/>\n");
		
		sb.append("<key attr.name=\"description\" attr.type=\"string\" for=\"node\" id=\"d3\"/>\n");
		
		sb.append("<key for=\"node\" id=\"d4\" yfiles.type=\"nodegraphics\"/>\n");
		
		
		// ###EDGE###
		sb.append("<key attr.name=\"description\" attr.type=\"string\" for=\"edge\" id=\"d10\"/>\n");
		
		sb.append("<key attr.name=\"distance\" attr.type=\"double\" for=\"edge\" id=\"d11\"/>\n");
		
		sb.append("<key attr.name=\"weight\" attr.type=\"double\" for=\"edge\" id=\"d12\"/>\n");
		
		sb.append("<key attr.name=\"url\" attr.type=\"string\" for=\"edge\" id=\"d13\"/>\n");
		
		sb.append("<key for=\"edge\" id=\"d15\" yfiles.type=\"edgegraphics\"/>\n");
		
		
		//#####GRAPH####
		sb.append("<graph edgedefault=\"undirected\" id=\"G\">\n");
		
		//show center
		if(settings.showCenter){
			sb.append("<node id=\"X\">\n");
			//<![CDATA[red]]>
			sb.append("<data key=\"d1");sb.append("\"><![CDATA[red]]></data>\n");
			sb.append("<data key=\"d2\"/>\n");
			sb.append("<data key=\"d3\"/>\n");
			sb.append("<data key=\"d4\">\n");
			sb.append("<y:ShapeNode>\n");
				sb.append("<y:Geometry height=\"10.0\" width=\"10.0\" x=\"-5.0\" y=\"-5.0\"/>\n");
				sb.append("<y:Fill color=\"#999999\" transparent=\"true\"/>\n");
				sb.append("<y:BorderStyle hasColor=\"false\" type=\"line\" width=\"0.0\"/>\n");
				sb.append("<y:NodeLabel alignment=\"center\" autoSizePolicy=\"content\" borderDistance=\"0.0\" fontFamily=\"Dialog\" fontSize=\"20\" fontStyle=\"plain\" hasBackgroundColor=\"false\" hasLineColor=\"false\" height=\"4.0\" modelName=\"internal\" modelPosition=\"c\" textColor=\"#000000\" visible=\"true\" width=\"4.0\" x=\"13.0\" y=\"13.0\">");sb.append("X");sb.append("</y:NodeLabel>\n");
				sb.append("<y:Shape type=\"ellipse\"/>\n");
			sb.append("</y:ShapeNode>\n");
			sb.append("</data>\n");
			sb.append("</node>\n");
		}
		
		//show inner city
		if(settings.showInnerCity){
			sb.append("<node id=\"InC\">\n");
			//<![CDATA[red]]>
			sb.append("<data key=\"d1");sb.append("\"><![CDATA[red]]></data>\n");
			sb.append("<data key=\"d2\"/>\n");
			sb.append("<data key=\"d3\"/>\n");
			sb.append("<data key=\"d4\">\n");
			sb.append("<y:ShapeNode>\n");
				sb.append("<y:Geometry height=\"");sb.append(settings.radiusCircle*2);sb.append("\" width=\"");sb.append(settings.radiusCircle*2);sb.append("\" x=\"");sb.append(settings.radiusCircle/-1);sb.append("\" y=\"");sb.append(settings.radiusCircle/-1);sb.append("\"/>\n");
				sb.append("<y:Fill color=\"#cccccc\" transparent=\"true\"/>\n");
				sb.append("<y:BorderStyle color=\"#000000\" type=\"line\" width=\"0.0\"/>\n");
				sb.append("<y:NodeLabel alignment=\"center\" autoSizePolicy=\"content\" borderDistance=\"0.0\" fontFamily=\"Dialog\" fontSize=\"13\" fontStyle=\"plain\" hasBackgroundColor=\"false\" hasLineColor=\"false\" height=\"4.0\" modelName=\"internal\" modelPosition=\"c\" textColor=\"#000000\" visible=\"true\" width=\"4.0\" x=\"13.0\" y=\"13.0\">");sb.append("");sb.append("</y:NodeLabel>\n");
				sb.append("<y:Shape type=\"ellipse\"/>\n");
			sb.append("</y:ShapeNode>\n");
			sb.append("</data>\n");
			sb.append("</node>\n");
		}
		
		//show outer border of all graph
		if(settings.showOuterBorder){
			sb.append("<node id=\"OuB\">\n");
			//<![CDATA[red]]>
			sb.append("<data key=\"d1");sb.append("\"><![CDATA[red]]></data>\n");
			sb.append("<data key=\"d2\"/>\n");
			sb.append("<data key=\"d3\"/>\n");
			sb.append("<data key=\"d4\">\n");
			sb.append("<y:ShapeNode>\n");
				sb.append("<y:Geometry height=\"");sb.append(settings.yBoard);sb.append("\" width=\"");sb.append(settings.yBoard);sb.append("\" x=\"");sb.append(settings.xBoard/-2);sb.append("\" y=\"");sb.append(settings.yBoard/-2);sb.append("\"/>\n");
				sb.append("<y:Fill color=\"#cccccc\" transparent=\"true\"/>\n");
				sb.append("<y:BorderStyle color=\"#000000\" type=\"line\" width=\"0.0\"/>\n");
				sb.append("<y:NodeLabel alignment=\"center\" autoSizePolicy=\"content\" borderDistance=\"0.0\" fontFamily=\"Dialog\" fontSize=\"13\" fontStyle=\"plain\" hasBackgroundColor=\"false\" hasLineColor=\"false\" height=\"4.0\" modelName=\"internal\" modelPosition=\"c\" textColor=\"#000000\" visible=\"true\" width=\"4.0\" x=\"13.0\" y=\"13.0\">");sb.append("");sb.append("</y:NodeLabel>\n");
				sb.append("<y:Shape type=\"rectangle\"/>\n");
			sb.append("</y:ShapeNode>\n");
			sb.append("</data>\n");
			sb.append("</node>\n");
		}
		
		
		//first level points-all
		for(int i=0;i<board.getPoints();i++){
			//stage is not beginning and point has no connections=don't print that!
			if(!Board.map.get(i).solitude == true){
			
			sb.append("<node id=\"");sb.append(Board.map.get(i).name);sb.append("\">\n");
			//<![CDATA[red]]>
			sb.append("<data key=\"d1");sb.append("\"><![CDATA[red]]></data>\n");
			sb.append("<data key=\"d2\"/>\n");
			sb.append("<data key=\"d3\"/>\n");
			sb.append("<data key=\"d4\">\n");
			sb.append("<y:ShapeNode>\n");
				sb.append("<y:Geometry height=\"10.0\" width=\"10.0\" x=\"");sb.append(Board.map.get(i).x);sb.append("\" y=\"");sb.append(Board.map.get(i).y);sb.append("\"/>\n");
				if(Board.map.get(i).centre = true)
					sb.append("<y:Fill color=\"#FFCC00\" transparent=\"false\"/>\n");
				else
					sb.append("<y:Fill color=\"#00FFFF\" transparent=\"false\"/>\n");
				sb.append("<y:BorderStyle color=\"#000000\" type=\"line\" width=\"0.0\"/>\n");
				sb.append("<y:NodeLabel alignment=\"center\" autoSizePolicy=\"content\" borderDistance=\"0.0\" fontFamily=\"Dialog\" fontSize=\"13\" fontStyle=\"plain\" hasBackgroundColor=\"false\" hasLineColor=\"false\" height=\"4.0\" modelName=\"internal\" modelPosition=\"c\" textColor=\"#000000\" visible=\"true\" width=\"4.0\" x=\"13.0\" y=\"13.0\">");sb.append(Board.map.get(i).name);sb.append("</y:NodeLabel>\n");
				sb.append("<y:Shape type=\"ellipse\"/>\n");
			sb.append("</y:ShapeNode>\n");
			sb.append("</data>\n");
			sb.append("</node>\n");
			}
		}
		//first level joins
		for(int i=0;i<board.getPoints();i++){
			for(int j=0;j<board.getPoints();j++){
				if(Board.matrixOfJoins[i][j].isConnected()){
					sb.append("<edge id=\"");sb.append(i+""+j);sb.append("\" source=\"");sb.append(i);sb.append("\" target=\"");sb.append(j);sb.append("\">\n");
						sb.append("<data key=\"d10\"><![CDATA[");sb.append(i+"-"+j);sb.append("]]></data>\n");
						sb.append("<data key=\"d11\">");sb.append(Board.matrixOfJoins[i][j].getDistance());sb.append("</data>\n");
						sb.append("<data key=\"d12\">");sb.append(Board.matrixOfJoins[i][j].getWeigth());sb.append("</data>\n");
						sb.append("<data key=\"d15\">\n");
					      	sb.append("<y:PolyLineEdge>\n");
					      		sb.append("<y:Path sx=\"0.0\" sy=\"0.0\" tx=\"0.0\" ty=\"0.0\"/>\n");
					    		sb.append("<y:LineStyle color=\"#00CC00\" type=\"line\" width=\"1.0\"/>\n"); //width -> weigth/distance
					    		sb.append("<y:Arrows source=\"none\" target=\"none\"/>\n");
					    		sb.append("<y:BendStyle smoothed=\"false\"/>\n");
					    	sb.append("</y:PolyLineEdge>\n");
					    sb.append("</data>\n");
				    sb.append("</edge>\n");
				}
				
				
			}
			
		}
		
		
		//second level joins
		for(int i=0;i<board.getPoints();i++){
			for(int j=0;j<board.getPoints();j++){
				if(Board.matrixOfJoins[i][j].isSLConnected()){
					sb.append("<edge id=\"");sb.append(i+"SL"+j);sb.append("\" source=\"");sb.append(i);sb.append("\" target=\"");sb.append(j);sb.append("\">\n");
					sb.append("<data key=\"d10\"><![CDATA[");sb.append(i+"-SL-"+j);sb.append("]]></data>\n");
					sb.append("<data key=\"d11\">");sb.append(Board.matrixOfJoins[i][j].getSLDistance());sb.append("</data>\n");
					sb.append("<data key=\"d12\">");sb.append(Board.matrixOfJoins[i][j].SLweigth);sb.append("</data>\n");
					sb.append("<data key=\"d15\">\n");
				      	sb.append("<y:PolyLineEdge>\n");
				      		sb.append("<y:Path sx=\"2.0\" sy=\"2.0\" tx=\"2.0\" ty=\"2.0\"/>\n");
				    		sb.append("<y:LineStyle color=\"#FF66FF\" type=\"line\" width=\"2.0\"/>\n"); //width -> weigth/distance 
				    		sb.append("<y:Arrows source=\"none\" target=\"none\"/>\n");
				    		sb.append("<y:BendStyle smoothed=\"false\"/>\n");
				    	sb.append("</y:PolyLineEdge>\n");
				    sb.append("</data>\n");
			    sb.append("</edge>\n");
				}
				
				
			}
			
		}
		
		
		//###End Type###
		sb.append("</graph>\n");
		sb.append("</graphml>\n");


		File fil;
		
		
		try{
			    // Create file
			 	
			 	fil = new File(settings.outputGraphML);
			 			
			    FileWriter fstream = new FileWriter(fil);
			        BufferedWriter out = new BufferedWriter(fstream);
			        
			    out.write(sb.toString());
			    //Close the output stream
			    out.close();
			    }catch (Exception e){//Catch exception if any
			    	log.error("Output ERROR", e);
					}
			    
			    
		
		return null;
	}
}
